/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2019-2019.
 * Description: led common driver
 * Author: zhangwen
 * Create: 2019-10-26
 */
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>

#include "led_common.h"

struct drol_op led_op_init[LED_OP_MAX];
struct drol_op led_op_on[LED_OP_MAX];
struct drol_op led_op_off[LED_OP_MAX];

struct drol_led drol_led_match[] = {
	{.name = "led-init", .op = led_op_init},
	{.name = "led-on", .op = led_op_on},
	{.name = "led-off", .op = led_op_off},
	{}
};

bool is_led_use_new_arch(void)
{
	if (of_find_compatible_node(NULL, NULL, "rtos_led_fixpart")
		|| of_find_compatible_node(NULL, NULL, "rtos_led_cpld_fixpart"))
		return false;
	else
		return true;
}

int led_type = LED_NO_DEVICE;

static int led_node_init(const char *name, struct drol_op *op,
		drol_map map, drol_unmap unmap)
{
	int nr;
	int ret;

	nr = drol_get_op(op, LED_OP_MAX, name, NULL);
	if (nr < 0)
		return 0;

	ret = drol_map_op(op, nr, map, unmap);
	if (ret)
		return ret;

	drol_do_op(op, nr);

	return nr;
}

void led_base_init(drol_map map, drol_unmap unmap)
{
	int i;
	struct device_node *np = NULL;
	struct drol_led *matches = NULL;

	np = of_find_compatible_node(NULL, NULL, "rtos_led_ctrl");
	if (!np) {
		pr_warn("can't find led ctrl node, please check it\n");
		return;
	}

	if (of_property_match_string(np, "type", "gpio") >= 0)
		led_type = LED_GPIO; /* gpio */

	matches = drol_led_match;
	for (i = 0; i < LED_END; i++) {
		matches[i].op_nr = led_node_init(matches[i].name, matches[i].op, map, unmap);
		if (matches[i].op_nr < 0) {
			pr_err("%s failed %d\n", matches[i].name, matches[i].op_nr);
			return;
		}
	}
}

void led_unmap(drol_unmap unmap)
{
	int i;
	struct drol_led *matches = NULL;

	matches = drol_led_match;

	for (i = 0; i < LED_END; i++)
		drol_unmap_op(matches[i].op, matches[i].op_nr, unmap);
}

void led_map(drol_map map, drol_unmap unmap)
{
	int i;
	struct drol_led *matches = NULL;

	matches = drol_led_match;

	for (i = 0; i < LED_END; i++) {
		if (drol_map_op(matches[i].op, matches[i].op_nr, map, unmap)) {
			pr_err("led %s map failed\n", matches[i].name);
			return;
		}
	}
}
#ifdef CONFIG_ACPI
int led_acpi_node_int(struct acpi_device *dev, const char *name,
	struct drol_op *op, drol_map map, drol_unmap unmap)
{
	int ret;
	int nr;

	if (!op || !name || !dev)
		return -EINVAL;

	nr =  acpi_reg_get_op(dev, name, op, LED_OP_MAX);
	if (nr < 0)
		return 0;

	ret = drol_map_op(op, nr, map, unmap);
	if (ret)
		return ret;

	drol_do_op(op, nr);
	return nr;
}

void led_acpi_base_init(struct acpi_device *dev, drol_map map, drol_unmap unmap)
{
	int i;
	struct drol_led *matches = NULL;

	if (acpi_reg_match_string(dev, "type", "gpio") >= 0)
		led_type = LED_GPIO; /* gpio */

	matches = drol_led_match;
	for (i = 0; i < LED_END; i++) {
		matches[i].op_nr = led_acpi_node_int(dev, matches[i].name, matches[i].op, map, unmap);
		if (matches[i].op_nr < 0) {
			pr_err("%s failed %d\n", matches[i].name, matches[i].op_nr);
			return;
		}
	}
}
#endif
